package templateExecel2.fram;

import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import templateExecel2.utils.PoiUtils;
import templateExecel2.utils.TemplateUtils;

import java.io.File;
import java.io.FileInputStream;
import java.util.*;

public final class Renderer {


    private Renderer() {
    }


    public static void render(XSSFSheet templateSheet, XSSFSheet targetSheet) {
        render(Data.getData(), templateSheet, targetSheet);
    }


    public static void render(Map<String, Object> data, XSSFSheet templateSheet, XSSFSheet targetSheet) {

        //放入目标数据
        Js.putAll(data);

        //复制样式
        PoiUtils.copySheet(templateSheet, targetSheet);

        //处理列宽
        PoiUtils.handleColumnWidth(templateSheet, targetSheet);

        //读取内容
        Map<Integer, Map<Integer, Object>> templateRow = PoiUtils.readSheet(templateSheet);

        //模板展开为实际数据
        Map<Integer, List<Map<Integer, Object>>> map = templateRowToValueRows(templateRow);

        //复制数据
        //PoiUtils.copySheetDataWithData(srcSheet, targetSheet, map);

        //TODO 赋值数据
        TemplateUtils.copySheetDataWithData(templateSheet, targetSheet, map);

    }

    public static XSSFWorkbook render(File template) throws Exception {
        return render(Data.getData(), template);
    }

    //根据模板将原数据进行渲染
    public static XSSFWorkbook render(Map<String, Object> data, File template, String... templateSheetNames) throws Exception {

        Js.putAll(data);

        //创建Excel文件
        FileInputStream inputStream = new FileInputStream(template);
        XSSFWorkbook src = PoiUtils.read(inputStream);
        inputStream.close();

        inputStream = new FileInputStream(template);
        XSSFWorkbook target = PoiUtils.read(inputStream);
        inputStream.close();

        List<String> list = Arrays.asList(templateSheetNames);

        //遍历所有的sheet页
        for (int i = 0; i < src.getNumberOfSheets(); i++) {
            XSSFSheet srcSheet = src.getSheetAt(i);

            XSSFSheet targetSheet = target.getSheet(srcSheet.getSheetName());

            if (list.size() > 0 && !list.contains(srcSheet.getSheetName())) {

                //不用执行删除,将原数据带着

        /*        if (targetSheet != null) {
                    target.removeSheetAt(target.getSheetIndex(targetSheet.getSheetName()));
                }
        */
                continue;
            }

            if (targetSheet == null) {
                target.createSheet(srcSheet.getSheetName());
            } else {
                for (int j = 0; j <= targetSheet.getLastRowNum(); j++) {
                    XSSFRow row = targetSheet.getRow(j);
                    if (row != null) {
                        targetSheet.removeRow(row);
                    }
                }
            }

            //复制样式
            PoiUtils.copySheet(srcSheet, targetSheet);

            //处理列宽
            PoiUtils.handleColumnWidth(srcSheet, targetSheet);

            //读取内容
            Map<Integer, Map<Integer, Object>> templateRow = PoiUtils.readSheet(srcSheet);

            //模板展开为实际数据
            Map<Integer, List<Map<Integer, Object>>> map = templateRowToValueRows(templateRow);

            //复制数据
            //PoiUtils.copySheetDataWithData(srcSheet, targetSheet, map);

            //TODO 赋值数据
            TemplateUtils.copySheetDataWithData(srcSheet, targetSheet, map);

        }

        return target;

    }

    //对于纯数字和日期等非字符串等,直接渲染
    private static Map<Integer, List<Map<Integer, Object>>> templateRowToValueRows(Map<Integer, Map<Integer, Object>> templateRow) {

        Map<Integer, List<Map<Integer, Object>>> map = new HashMap<>();

        templateRow.forEach((rowNumber, row) -> {

            Map<String, Integer> max = new HashMap<>();

            Map<Integer, TemplateCell> values = new HashMap<>();

            //遍历一行模板
            row.forEach((colNumber, col) -> {

                //解析结果
                TemplateCell parse = TemplateCell.parse(col);
                try {
                    parse.exe();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }

                values.put(colNumber, parse);

                Map<String, Integer> indexMax = parse.getIndexMax();
                if (indexMax != null) {
                    indexMax.forEach((name, maxValue) -> {
                        Integer integer = max.get(name);
                        if (integer == null || maxValue > integer) {
                            max.put(name, maxValue);
                        }
                    });
                }

            });

            //
            if (max.size() > 0) {
                AutoIncrementNumber autoIncrementNumber = new AutoIncrementNumber();
                autoIncrementNumber.init(max);

                List<Map<Integer, Object>> list = new ArrayList<>();
                //自增
                out:
                while (autoIncrementNumber.autoIncrement()) {

                    int index = autoIncrementNumber.getIndex();

                    //为什么无效???

                    Js.set("_index", index);

                    Map<Integer, Object> line = new HashMap<>();

                    //如果有一个元素是无效的就直接返回
                    for (Integer colValue : values.keySet()) {
                        TemplateCell tc = values.get(colValue);
                        try {
                            line.put(colValue, tc.get(autoIncrementNumber.getValues()));
                        } catch (InvalidIndexException e) {
                            continue out;
                        }
                    }
                    if (line.size() > 0) {
                        list.add(line);
                    }
                }
                Js.remove("_index");

                if (list.size() > 0) {
                    map.put(rowNumber, list);
                }

            } else {
                List<Map<Integer, Object>> list = new ArrayList<>();
                Map<Integer, Object> line = new HashMap<>();
                values.forEach((colValue, tc) -> {
                    line.put(colValue, tc.getSingleResult());
                });
                if (line.size() > 0) {
                    list.add(line);
                    map.put(rowNumber, list);
                }
            }

            try {

                //清空缓存,防止内存溢出
                Js.call("_clearCache");
            } catch (Exception e) {

            }

        });

        return map;
    }

    /**
     * 将原数据进行渲染
     *
     * @param data               源数据
     * @param template           模板Excel文件
     * @param target             目标Excel文件
     * @param templateSheetNames 模板文件中需要被渲染的Sheet页名称
     */
    public static void render(Map<String, Object> data, File template, File target, String... templateSheetNames) throws Exception {

        if (!target.exists()) {
            if (!target.createNewFile()) {
                throw new RuntimeException("目标文件创建失败");
            }
        }

        // FileUtils.copy(template, target);

        XSSFWorkbook render = render(data, template, templateSheetNames);

        PoiUtils.write(render, target);

    }


    public static void render(File template, File target, String... templateSheetNames) throws Exception {
        render(Data.getData(), template, target);
    }

}

